/*
 * Java CMPP API
 * Copyright (C) 1998 - 2002 by Xu Youming
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * A copy of the LGPL can be viewed at http://www.gnu.org/copyleft/lesser.html
 * Java CMPP API author: xuym@bc-info.net
 * Java CMPP API Homepage: http://cmppapi.sourceforge.net/
 * $Id: CMPPEventAdapter.java,v 1.1 2008/03/19 02:56:56 xym Exp $
 */
package com.bci.cmpp.event;

import com.bci.cmpp.CMPPConstants;
import com.bci.cmpp.Connection;
import com.bci.cmpp.message.*;

import org.apache.commons.logging.LogFactory;

/**
 * Base class for applications to extend for CMPP event handling. This class
 * handles incoming events and provides a set of blank handler methods for the
 * various events. This makes it easy for an application to extend this class
 * and only override the methods it's interested in.
 * 
 * @author Xu Youming
 * @version 1.0
 */
public abstract class CMPPEventAdapter implements ConnectionObserver {
	/**
	 * Default constructor.
	 */
	public CMPPEventAdapter() {
	}

	public final void update(Connection source, CMPPEvent event) {
		try {
			switch (event.getType()) {
			case CMPPEvent.RECEIVER_START:
				receiverStart(source, (ReceiverStartEvent) event);
				break;

			case CMPPEvent.RECEIVER_EXIT:
				ReceiverExitEvent ree = (ReceiverExitEvent) event;
				if (ree.getReason() == ReceiverExitEvent.EXCEPTION)
					receiverExitException(source, ree);
				else
					receiverExit(source, ree);
				break;

			case CMPPEvent.RECEIVER_EXCEPTION:
				receiverException(source, (ReceiverExceptionEvent) event);
				break;

			default:
				userEvent(source, event);
			}
		} catch (ClassCastException x) {
			LogFactory.getLog(CMPPEventAdapter.class).error(
					"Class cast exception", x);
		}
	}

	public final void packetReceived(Connection source, CMPPPacket pak) {
		// Keep high-incidence packet types at the top of this switch.
		switch (pak.getCommandId()) {
		case CMPPConstants.CMPP_DELIVER:
			if (source.getVersion() == CMPPConstants.CMPP_VERSION_2)
				deliverSM(source, (CMPPDeliver) pak);
			else
				deliverSM(source, (CMPPDeliver30) pak);
			break;

		case CMPPConstants.CMPP_SUBMIT_RESP:
			submitSMResponse(source, (CMPPSubmitResp) pak);
			break;

//		case CMPPConstants.CMPP_SUBMIT_MULTI:
			// submitMultiResponse(source, (CMPPSubmitMulti) pak);
//			break;

		case CMPPConstants.CMPP_CANCEL:
			cancelSMResponse(source, (CMPPCancel) pak);
			break;

		case CMPPConstants.CMPP_QUERY_RESP:
			queryResponse(source, (CMPPResponse) pak);
			break;

		case CMPPConstants.CMPP_ACTIVE_TEST:
			try{
			queryLink(source, (CMPPActiveTest) pak);
			}catch(Exception e){
				e.printStackTrace();
			}
			break;

		case CMPPConstants.CMPP_ACTIVE_TEST_RESP:
			queryLinkResponse(source, (CMPPActiveTestResp) pak);
			break;

		case CMPPConstants.CMPP_TERMINATE:
			unbind(source, (CMPPTerminate) pak);
			break;

		case CMPPConstants.CMPP_TERMINATE_RESP:
			unbindResponse(source, (CMPPTerminateResp) pak);
			break;

		case CMPPConstants.CMPP_CONNECT_RESP:
			// case CMPPConstants.BIND_TRANSCEIVER_RESP:
			// case CMPPConstants.BIND_RECEIVER_RESP:
			bindResponse(source, (CMPPConnectResp) pak);
			break;

		default:
			unidentified(source, pak);
			break;
		}
	}

	/**
	 * Receiver thread exited normally. This method is called by the event
	 * adapter when it receives a receiver exit event from the API that does not
	 * contain an exception. This normally means that either the SMSG has
	 * requested an unbind and the response has been successfully sent or that
	 * an unbind request has been successfully acknowledged.
	 * 
	 * @param source
	 *            the source connection of the event.
	 * @param rev
	 *            the receiver exit event object received from the API.
	 */
	public void receiverExit(Connection source, ReceiverExitEvent rev) {
		// default: do nothing
	}

	/**
	 * Receiver thread exited due to fatal exception. This method is called by
	 * the event adapter when the receiver thread has exited due to an exception
	 * it caught. Handling code for this method should assume that the CMPP link
	 * to the SMSG and probably the network-specific connection has been lost.
	 * It should do any clean up and either exit gracefully or re-establish the
	 * network connection and re-bind to the SMSG.
	 * 
	 * @param source
	 *            the source connection of the event.
	 * @param rev
	 *            the receiver exit event object received from the API.
	 */
	public void receiverExitException(Connection source, ReceiverExitEvent rev) {
		// default: do nothing
	}

	/**
	 * Receiver thread caught a non-fatal exception. This method is called when
	 * an exception has been caught by the receiver thread but it is not exiting
	 * due to it. If this method gets called it may be indicitive of a network
	 * communications error or possibly an unidentified incoming packet type
	 * from the SMSG.
	 * 
	 * @param source
	 *            the source connection of the event.
	 * @param rev
	 *            the receiver exception event received from the API, which
	 *            contains the caught exception.
	 */
	public void receiverException(Connection source, ReceiverExceptionEvent rev) {
		// default: do nothing
	}

	/**
	 * Receiver thread has started up. This method is called when the receiver
	 * thread starts. Most applications will ignore this event and just use the
	 * default (blank) implementation of this method.
	 * 
	 * @param source
	 *            the source connection of the event.
	 * @param rs
	 *            the receiver start event received from the API.
	 */
	public void receiverStart(Connection source, ReceiverStartEvent rs) {
		// default: do nothing
	}

	/**
	 * PLACEHOLDER. This method will currently never be called.
	 */
	public void userEvent(Connection source, CMPPEvent ev) {
		// default: do nothing
	}

	/**
	 * DeliverSM packet received from the SMSG.
	 */
	public abstract void deliverSM(Connection source, CMPPDeliver dm);

	/**
	 * DeliverSM packet received from the SMSG.
	 */
	public abstract void deliverSM(Connection source, CMPPDeliver30 dm);

	/**
	 * SubmitSM response packet received from the SMSG.
	 */
	public abstract void submitSMResponse(Connection source, CMPPSubmitResp smr);

	/**
	 * SubmitMulti response packet received from the SMSG.
	 */
	// public void submitMultiResponse(Connection source, SubmitMultiResp smr) {
	// }
	/**
	 * CancelSM response packet received from the SMSG.
	 */
	public abstract void cancelSMResponse(Connection source, CMPPCancel cmr);

	/**
	 * ReplaceSM response packet received from the SMSG.
	 */
	// public void replaceSMResponse(Connection source, CMPPReplace rmr) {
	// }
	/**
	 * ParamRetrieve response packet received from the SMSG.
	 */
	// public void paramRetrieveResponse(Connection source, ParamRetrieveResp
	// prr) {
	// }
	/**
	 * One of a QuerySM, QueryLastMsgs or QueryMsgDetails response packet has
	 * been received from the SMSG.
	 */
	public abstract void queryResponse(Connection source, CMPPResponse qr) ;

	/**
	 * EnquireLink packet received from the SMSG.
	 */
	public abstract void queryLink(Connection source, CMPPActiveTest el) ;
	

	/**
	 * EnquireLink response packet received from the SMSG.
	 */
	public abstract void queryLinkResponse(Connection source, CMPPActiveTestResp elr) ;
	

	/**
	 * Unbind packet received from the SMSG.
	 */
	public abstract void unbind(Connection source, CMPPTerminate ubd) ;
	

	/**
	 * Unbind response packet received from the SMSG.
	 */
	public abstract void unbindResponse(Connection source, CMPPTerminateResp ubr);

	/**
	 * Bind response packet received from the SMSG.
	 */
	public abstract void bindResponse(Connection source, CMPPConnectResp br) ;

	public abstract void bindResponse(Connection source, CMPPConnectResp30 br) ;
	/**
	 * GenericNack packet received from the SMSG.
	 */
	// public void genericNack(Connection source, GenericNack nack) {
	// }
	/**
	 * An unidentified packet has been received from the SMSG.
	 */
	public abstract void unidentified(Connection source, CMPPPacket pak);
}